/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.gui.server;

import java.io.DataInputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;

import javax.net.*;
import java.net.*;
import java.util.*;
import java.sql.*;

import nfse.NetFSE;
import nfse.NetFSERecord;
import nfse.NetFSEUtil;

public class QueryThread extends Thread {

    String queryID = "";

    String[] queries = null;

    int[] types = null;

    Statement statement = null;

    long total = 1000000;

    long limit = 1000000;

    public QueryThread(String queryID, String[] queries, int[] types, Statement statement, long total, long limit) {
        this.queryID = queryID;
        this.queries = queries;
        this.types = types;
        this.statement = statement;
        this.total = total;
        this.limit = limit;
    }

    public void run() {
        Socket socket = null;
        Socket socket2 = null;
        DataInputStream resultIn = null;
        try {
            String insertSQL = "";
            ResultSet rs = null;
            for (int x = 0; x < queries.length; x++) {
                // SocketFactory sf = SSLSocketFactory.getDefault();
                SocketFactory sf = SocketFactory.getDefault();
                socket = sf.createSocket(NetFSE.QUERY_HOST, NetFSE.QUERY_SERVER_PORT);
                PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
                DataInputStream socketIn = new DataInputStream(socket.getInputStream());

                ServerSocketFactory ssf = ServerSocketFactory.getDefault();
                ServerSocket ss = ssf.createServerSocket();
                try {

                    if ((queries[x].indexOf(" user=\"") > 0) && (queries[x].indexOf(" password=\"") > 0)) {
                        // no op
                    }

                    int endIdx = queries[x].lastIndexOf("</Query>");
                    if (endIdx >= 0) {
                        queries[x] = queries[x].substring(0, endIdx);
                    } else {
                        endIdx = queries[x].lastIndexOf("/>");
                        queries[x] = queries[x].substring(0, endIdx) + ">";
                    }

                    ss.bind(null);

                    queries[x] += "<SocketResult host=\"" + NetFSE.TOMCAT_HOST + "\" port=\"" + ss.getLocalPort()
                            + "\"/>";

                    queries[x] += "</Query>";

                    long start = System.currentTimeMillis();
                    socketOut.println(queries[x]);
                    socketOut.println("<--DiSARM: end query-->");
                    socketOut.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // out.println(queries[x] + "<br>");

                int reply = socketIn.readInt();
                if (reply >= 0)
                    socket2 = ss.accept();

                if (reply < 0) {
                    statement.close();
                    return;
                } else {
                    
                    
                    resultIn = new DataInputStream(socket2.getInputStream());
                    long start = System.currentTimeMillis();
                    int count = 0;
                    int[] counts = new int[types.length];

                    int type = -1;
                    int sensor = -1;
                    int len = -1;
                    byte[] bytes = null;
                    int bytesRead;
                    String line = null;
                    try {
                        type = resultIn.readInt();
                        if (type == -100) {
                            line = null;
                        } else {
                            sensor = resultIn.readInt();
                            len = resultIn.readInt();
                            bytes = new byte[len];
                            bytesRead = 0;
                            while (bytesRead < len)
                                bytesRead += resultIn.read(bytes, bytesRead, len - bytesRead);
                            // for (int j = 0; j < len; j++)
                            // bytes[j] = (byte) resultIn.read();

                            line = new String(bytes);
                        }
                    } catch (Exception E) {
                        line = null;
                    }
                    insertSQL = "";
                    NetFSERecord rec = NetFSE.getTypeClass(type);
                    NetFSERecord temp = null;
                    int typeCount = 0;
                    
                    while (line != null) {
                        
                        if ((total != -1) && (count == total)) {
                            line = null;
                            break;
                        }

                        if ((limit == -1) || (typeCount < limit)) {
                            try {
                                count++;
                                temp = rec.generate(line, sensor);
                                //System.out.println(line);
                                if (temp != null) {
                                    insertSQL = temp.getInsertFieldTableSQL(count, queryID + "_" + type);
                                    //inserts1.addElement(insertSQL);
                                    statement.execute(insertSQL);
                                    insertSQL = " insert into " + queryID + " values (" + count + "," + type + ","
                                            + sensor + ",'" + NetFSEUtil.convertToHex(line) + "')";
                                    //inserts2.addElement(insertSQL);
                                    statement.execute(insertSQL);
                                    typeCount++;
                                } else
                                    count--;
                            } catch (Exception e) {
                                System.out.println(insertSQL);
                                e.printStackTrace();
                                count--;
                                typeCount--;
                            }
                        } else {
                            line = null;
                        }

                        if (count % 1000 == 0) {
                            long rps = count / ((System.currentTimeMillis() - start) / 1000);
                            //statement.execute("begin");
                            //for (int i = 0; i < inserts1.size(); i++) {
                            //    statement.execute((String)inserts1.elementAt(i));
                            //    statement.execute((String)inserts2.elementAt(i));
                           // }
                            //statement.execute("commit");
                            //inserts1.removeAllElements();
                            //inserts2.removeAllElements();
                        }

                        if (line != null) {
                            try {
                                type = resultIn.readInt();
                                if (type == -100) {
                                    line = null;
                                } else {
                                    sensor = resultIn.readInt();
                                    len = resultIn.readInt();
                                    bytes = new byte[len];
                                    bytesRead = 0;
                                    while (bytesRead < len)
                                        bytesRead += resultIn.read(bytes, bytesRead, len - bytesRead);

                                    // for (int j = 0; j < len; j++)
                                    // bytes[j] = (byte) resultIn.read();
                                    line = new String(bytes);
                                }
                            } catch (Exception E) {
                                E.printStackTrace();
                                line = null;
                            }
                        }

                    } // End main while loop
                    
                   //System.out.println("COUNT WAS " + count);

                   // if (inserts1.size() > 0) {
                        //statement.execute("begin");
                        //for (int i = 0; i < inserts1.size(); i++) {
                        //    statement.execute((String)inserts1.elementAt(i));
                        //    statement.execute((String)inserts2.elementAt(i));
                        //}
                        //statement.execute("commit");
                        //inserts1.removeAllElements();
                        //inserts2.removeAllElements();
                   // }
                    // for (int i = 0; i < types.length; i++) {
                    // }

                }
                
                rs = statement.executeQuery("select count(*) as a from " + queryID + " where Type_ID=" + types[x]);
                rs.next();
                int cnt = rs.getInt("a");
                rs.close();
                statement.execute("update Query_Types set Count=" + cnt + " where Query_ID='" + queryID
                        + "' and Type_ID=" + types[x]);

                if (resultIn != null) {
                    resultIn.close();
                }
                socketOut.close();
                socketIn.close();
                if (socket2 != null)
                    socket2.close();
                socket.close();
                ss.close();
            }

            rs = statement.executeQuery("select count(*) as a from " + queryID);
            rs.next();
            int cnt = rs.getInt("a");
            rs.close();
            statement
                    .execute("update Queries set Count=" + cnt + ", Status=" + 1 + " where Query_ID='" + queryID + "'");

            statement.close();
            // c.close();
        } catch (Exception E) {
            E.printStackTrace();
        }
    }

}
